#include "flip_internal.hpp"

#include <flip/gl/gl.hpp>
#include <flip/2d/geom_buffer.hpp>

LUAF(begin_quads)
{
	luaflipData& data = globalData(L);

	data.drawBuffer.geomQuads();
	return 0;
}

LUAF(quad)
{
	luaflipData& data = globalData(L);
	double v[8];

	v[0] = luaL_checknumber(L, 1);
	v[1] = luaL_checknumber(L, 2);
	v[2] = luaL_checknumber(L, 3);
	v[3] = luaL_checknumber(L, 4);
	v[4] = luaL_checknumber(L, 5);
	v[5] = luaL_checknumber(L, 6);
	v[6] = luaL_checknumber(L, 7);
	v[7] = luaL_checknumber(L, 8);

	data.drawBuffer.quad(
		(float)v[0], (float)v[1], (float)v[2], (float)v[3],
		(float)v[4], (float)v[5], (float)v[6], (float)v[7]);
	
	return 0;
}

LUAF(begin_sprites)
{
	luaflipData& data = globalData(L);

	data.drawBuffer.geomImages();
	return 0;
}

LUAF(sprite)
{
	luaflipData& data = globalData(L);
	auto& sprite = check_sprite(L, 1);

	float x = float(luaL_checknumber(L, 2));
	float y = float(luaL_checknumber(L, 3));

	data.drawBuffer.image(x, y, *sprite.data());
	
	return 0;
}

LUAF(sprite_centered)
{
	luaflipData& data = globalData(L);
	auto& sprite = check_sprite(L, 1);

	float x = float(luaL_checknumber(L, 2));
	float y = float(luaL_checknumber(L, 3));

	data.drawBuffer.imageCentered(x, y, *sprite.data());
	
	return 0;
}

LUAF(sprite_centered_rot)
{
	luaflipData& data = globalData(L);
	auto& sprite = check_sprite(L, 1);

	float x = float(luaL_checknumber(L, 2));
	float y = float(luaL_checknumber(L, 3));
	float ang = float(luaL_checknumber(L, 4));

	data.drawBuffer.imageCenteredRot(x, y, ang, *sprite.data());
	
	return 0;
}

LUAF(clear)
{
	glClear(GL_COLOR_BUFFER_BIT);
	return 0;
}

LUAF(color)
{
	luaflipData& data = globalData(L);
	double r = luaL_checknumber(L, 1);
	double g = luaL_checknumber(L, 2);
	double b = luaL_checknumber(L, 3);
	
	data.drawBuffer.color((float)r, (float)g, (float)b);
	return 0;
}

LUAF(draw_sprite)
{
	luaflipData& data = globalData(L);
	auto& sprite = check_sprite(L, 1);

	float x = float(luaL_checknumber(L, 2));
	float y = float(luaL_checknumber(L, 3));

	data.drawBuffer.geomQuads();
	data.drawBuffer.image(x, y, *sprite.data());
	return 0;
}

LUAF(lua_test_flush_buffers)
{
	using namespace Flip;

	luaflipData& data = globalData(L);

	int geomMode = int(lua_tointeger(L, 1));
	int curTex = int(lua_tointeger(L, 6));
	int isColored = lua_toboolean(L, 11);
	int itemCount = int(lua_tointeger(L, 5));
	double* vert = reinterpret_cast<double*>(luaext_rawarraybase(L, 2, itemCount));
	
	int vertexCount = itemCount / 2;

	float fvert[4096];
	float ftex[4096];
	float fcol[4096*2];

	for(int i = 0; i < itemCount; ++i)
	{
		fvert[i] = float(vert[i]);
	}

	if(isColored)
	{
		double* col = reinterpret_cast<double*>(luaext_rawarraybase(L, 4, itemCount * 2));
		for(int i = 0; i < itemCount*2; ++i)
			fcol[i] = float(col[i]);
		glEnableVertexAttribArray(AttribColor);
		glVertexAttribPointer(AttribColor, 4, GL_FLOAT, GL_FALSE, 0, fcol);
	}
	else
	{
		float colr = float(lua_tonumber(L, 7));
		float colg = float(lua_tonumber(L, 8));
		float colb = float(lua_tonumber(L, 9));
		float cola = float(lua_tonumber(L, 10));
		glVertexAttrib4f(AttribColor, colr, colg, colb, cola);
	}

	glEnableVertexAttribArray(AttribPosition);
	if(curTex >= 0)
	{
		double* tex = reinterpret_cast<double*>(luaext_rawarraybase(L, 3, itemCount));
		for(int i = 0; i < itemCount; ++i)
		{
			ftex[i] = float(tex[i]);
		}

		glBindTexture(GL_TEXTURE_2D, curTex);
		glEnableVertexAttribArray(AttribTexCoord);
		glVertexAttribPointer(AttribTexCoord, 2, GL_FLOAT, GL_FALSE, 0, ftex);
	}
	else
	{
		data.currentWindow.bindWhiteTexture();
		glVertexAttrib2f(AttribTexCoord, 0.f, 0.f);
	}
	glVertexAttribPointer(AttribPosition, 2, GL_FLOAT, GL_FALSE, 0, fvert);

	if(geomMode == GeomBuffer::Quad || geomMode == GeomBuffer::Image)
		glDrawArrays(GL_QUADS, 0, vertexCount);
	else if(geomMode == GeomBuffer::Line)
		glDrawArrays(GL_LINES, 0, vertexCount);
	else if(geomMode == GeomBuffer::TriFan)
		glDrawArrays(GL_TRIANGLE_FAN, 0, vertexCount);
	else if(geomMode == GeomBuffer::LineStrip)
		glDrawArrays(GL_LINE_STRIP, 0, vertexCount);
	else if(geomMode == GeomBuffer::Tri)
		glDrawArrays(GL_TRIANGLES, 0, vertexCount);
	else if(geomMode == GeomBuffer::Point)
		glDrawArrays(GL_POINTS, 0, vertexCount);

	if(isColored)
		glDisableVertexAttribArray(AttribColor);
	glDisableVertexAttribArray(AttribPosition);
	if(curTex >= 0)
		glDisableVertexAttribArray(AttribTexCoord);

	return 0;
}